//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:20-4-13
// @Time:下午5:16
//

#include <GeeJoan/ErrorModule.pb.h>
#include "SingleServer.h"
#include "Business/AuthBusiness.h"
#include "Business/IoTBusiness.h"
#include "GeeJoan/NetWorkPackage.pb.h"
#include "Server/ServerContext.h"
#include "Business/DataBase/DataBaseHelper.h"

#include "Business/CacheManager.h"

using namespace GeeJoan::Protocol;

class MyCodecType : public CodecBase
{
public:
    int tryDecode(Slice data, Slice &msg) override
    {
        if (data.size() == 1 && data[0] == 0x04)
        {
            msg = data;
            return 1;
        }

        if (data.size() > 5)
        {
            msg = Slice( data.data(), data.size());
            return data.size();
        }
        return 0;
    }

    void encode(Slice msg, Buffer &buf) override
    {
        buf.append( msg );
    }

    CodecBase *clone() override
    {
        return new LineCodec();
    }
};

int SingleServer::ConnentHello(const TcpConnPtr &con, std::string errorMsgData)
{
    NetWork::NetWorkPackageRespose respose;
    Error::ErrorMessage errorMessage;
    errorMessage.set_errmsg( errorMsgData );
    respose.set_taskid( 0 );
    respose.set_code( 200 );
    respose.set_type_m((NetWork::NetWorkPackageModel) 0 );
    respose.set_type_sub( 0 );
    respose.set_body( errorMessage.SerializeAsString());
    con->send( respose.SerializeAsString());
    return 0;
}

int SingleServer::ConnentCloseEvent(const TcpConnPtr &con)
{
    std::string currentToken = con->context<ServerContext>().getToken();

    auto findDevice = CacheManager::GetInstance()->deviceTokenMap.find( currentToken );

    if (findDevice != CacheManager::GetInstance()->deviceTokenMap.end())
    {
        // 存在会话
        CacheManager::GetInstance()->deviceTokenMap.erase( findDevice );
        info( "SingleServer::ConnentCloseEvent , delete findDevice success" );
    } else
    {
        error( "SingleServer::ConnentCloseEvent , delete findDevice fail " );
    }

    return 0;
}

int SingleServer::startServer()
{
//    setloglevel( "TRACE" );
    EventBase base; //事件分发器
    Signal::signal( SIGINT, [&] { base.exit(); } ); //注册Ctrl+C的信号处理器--退出事件分发循环

    DataBaseHelper dataBaseHelper( DATABASENAME );
    dataBaseHelper.tableCheckExists();
    TcpServerPtr server = TcpServer::startServer( &base, "", this->man_port ); //创建服务器
    exitif( server == NULL, "start tcpserver failed" );
    void *userdata = nullptr;
    server->onConnCreate( [&]
                          {
                              TcpConnPtr con( new TcpConn ); //每个用户对应一个con
                              // 创建 一个新的链接

                              // 设置连接的事件
                              // 状态变更事件
                              con->onState( [&](const TcpConnPtr &con)
                                            {

                                                if (con->getState() == TcpConn::Connected)
                                                {
                                                    // 新的 连接接入
                                                    con->context<ServerContext>() = ServerContext {};

                                                    ConnentHello( con, "hello" );
                                                } else if (con->getState() == TcpConn::Closed)
                                                {
                                                    // 链接关闭事件
                                                    info( "colse" );

                                                    ConnentCloseEvent( con );


                                                }
                                            } );

                              // 消息到达事件
                              con->onMsg( new MyCodecType, [&](const TcpConnPtr &con, Slice msg)
                              {

                                  // 过滤不支持的 数据包
                                  NetWork::NetWorkPackageRequest netWorkPackageRequest;
                                  for (int i = 0; i < msg.size(); ++i)
                                  {
                                      fprintf( stderr, "%02X", msg.data()[i] );
                                  }
                                  if (netWorkPackageRequest.ParseFromArray( msg.data(), msg.size()))
                                  {
                                      // 解包成功
                                      info( "netWorkPackageRequest success " );
                                      eventManager.dispatchMod( netWorkPackageRequest.type_m(),
                                                                netWorkPackageRequest.type_sub(),
                                                                netWorkPackageRequest.taskid(),
                                                                con,
                                                                (uint8_t *) netWorkPackageRequest.body().c_str(),
                                                                netWorkPackageRequest.body().length(),
                                                                userdata
                                      );

                                  } else
                                  {
                                      // 解包失败
                                      info( "netWorkPackageRequest fail " );
                                  }
                              } );
                              return con;
                          } );
    base.loop(); //进入事件分发循环
    info( "ChatServer exited" );
    return 0;
}

SingleServer::~SingleServer()
{
    google::protobuf::ShutdownProtobufLibrary();
}
